#pragma once
#include<iostream>
#include<string>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<unistd.h>
#include<cstdlib>
#include<cstring>
#include"Err.hpp"
#include"Log.hpp"
static const int gbacklog=32;
class Sock
{
public:
Sock():_sock(-1)
{

}
~Sock()
{}
void Socket()
{
    _sock=socket(AF_INET,SOCK_STREAM,0);
    if(_sock<0)
    {
        logMessage(Fatal,"socket error,code:%d,errstring:%s",errno,strerror(errno));
        exit(SOCKET_ERR);
    }
    
}
void Bind(const uint16_t& port)
{
    struct sockaddr_in local;
    memset(&local,0,sizeof(local));
    local.sin_family=AF_INET;
    local.sin_port=htons(port);
    local.sin_addr.s_addr=INADDR_ANY;
    if(bind(_sock,(struct sockaddr*)&local,sizeof(local))<0)
    {
        logMessage(Fatal,"bind error,code:%d,errstring:%s",errno,strerror(errno));
        exit(BIND_ERR);
    }
}
void Listen()
{
    if(listen(_sock,gbacklog)<0)
    {
        logMessage(Fatal,"listen error,code:%d,errstring:%s",errno,strerror(errno));
        exit(LISTEN_ERR);
    }
}
int Accept(std::string* clientip,uint16_t* clientport)
{
    struct sockaddr_in temp;
    socklen_t len=sizeof(temp);
    int sock=accept(_sock,(struct sockaddr*)&temp,&len);
    if(sock<0)
    {
        logMessage(Warning,"accept error,code:%d,errstring:%s",errno,strerror(errno));
        
    }
    else{
        *clientport=ntohs(temp.sin_port);
        *clientip=inet_ntoa(temp.sin_addr);
    }
    return sock;
}
int Connect(const std::string& serverip,const uint16_t& serverport)
{
    struct sockaddr_in server;
    memset(&server,0,sizeof(server));
    server.sin_family=AF_INET;
    server.sin_port=htons(serverport);
    server.sin_addr.s_addr=inet_addr(serverip.c_str());
    int n=connect(_sock,(struct sockaddr*)&server,sizeof(server));
    return n;
}
int Fd()
{
    return _sock;
}
private:
    int _sock;
};